<?
require_once(dirname(__FILE__) . '/../../classes/module_interface.inc.php');
require_once(dirname(__FILE__) . '/../../classes/strings.inc.php');
require_once(dirname(__FILE__) . '/config.inc.php');

class LoggerModuleSources extends LoggerStrings implements LoggerModuleInterface
{
    protected $database;

    public function __construct(LoggerDatabase $database) 
    {
        $this->database = $database;
        $this->stringsTable = 'module_sources_strings';
    }

    public function PrepareParseSession()
    {
        return true;
    }

    protected function DecodeString($string)
    {
//        $string = urldecode($string);
        if (function_exists('iconv') && !preg_match('#.#u', $string))
            $string = iconv('WINDOWS-1251', 'UTF-8//IGNORE', $string);
        return $string;
    }

    protected function DetectSearch($serverStr, $pathStr, $queryStr)
    {
        if (preg_match("/google\.(co\.|com\.|)\w{2,4}$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['q']))
                return false;

            $query = $this->DecodeString($arVariables['q']);
            $page = 1;
            if (isset($arVariables['start']))
            {
                $start = intval($arVariables['start']);
                $num = 10;
                if (isset($arVariables['num']))
                    $num = intval($arVariables['num']);
                $page = 1 + round($start / $num);
            }
            return array(
                'engine' => 'Google',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/yandex\.(ru|by|ua|kz)$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['text']))
                return false;

            $query = $this->DecodeString($arVariables['text']);
            $page = 1;
            if (isset($arVariables['p']))
            {
                $page = 1 + intval($arVariables['p']);
            }
            return array(
                'engine' => 'Yandex',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/go\.mail\.ru$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['q']))
                return false;

            $query = $this->DecodeString($arVariables['q']);
            $page = 1;
            if (isset($arVariables['sf']))
            {
                $start = intval($arVariables['sf']);
                $num = 10;
                if (isset($arVariables['num']))
                    $num = intval($arVariables['num']);
                $page = 1 + round($start / $num);
            }
            return array(
                'engine' => 'Mail.Ru',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/search\.yahoo\.com$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['p']))
                return false;

            $query = $this->DecodeString($arVariables['p']);
            $page = 1;
            if (isset($arVariables['b']))
            {
                $page = ceil($arVariables['b'] / 10);
            }
            return array(
                'engine' => 'Yahoo',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/bing\.com$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['q']))
                return false;

            $query = $this->DecodeString($arVariables['q']);
            $page = 1;
            if (isset($arVariables['first']))
            {
                $page = ceil($arVariables['first'] / 10);
            }
            return array(
                'engine' => 'Bing',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/nova\.rambler\.ru$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['query']))
                return false;

            $query = $this->DecodeString($arVariables['query']);
            $page = 1;
            if (isset($arVariables['page']))
            {
                $page = intval($arVariables['page']);
            }
            return array(
                'engine' => 'Rambler',
                'text' => $query,
                'page' => $page
            );
        }
    
        if (preg_match("/aport\.ru$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['r']))
                return false;

            $query = $this->DecodeString($arVariables['r']);
            $page = 1;
            if (isset($arVariables['p']))
            {
                $page = 1 + intval($arVariables['p']);
            }
            return array(
                'engine' => 'Aport',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/search\.tut\.by$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['query']))
                return false;

            $query = $this->DecodeString($arVariables['query']);
            $page = 1;
            if (isset($arVariables['page']))
            {
                $page = 1 + intval($arVariables['page']);
            }
            return array(
                'engine' => 'Tut.by',
                'text' => $query,
                'page' => $page
            );
        }

        if (preg_match("/gogo\.by$/i", $serverStr))
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['q']))
                return false;

            $query = $this->DecodeString($arVariables['q']);
            $page = 1;
            if (isset($arVariables['p']))
            {
                $page = 1 + intval($arVariables['p']);
            }
            return array(
                'engine' => 'Gogo.by',
                'text' => $query,
                'page' => $page
            );
        }

        if ($serverStr == 'raildex.vtb.rw:17000')
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['text']))
                return false;

            $query = $this->DecodeString($arVariables['text']);
            $page = 1;
            if (isset($arVariables['p']))
            {
                $page = 1 + intval($arVariables['p']);
            }
            return array(
                'engine' => 'raildex.vtb.rw',
                'text' => $query,
                'page' => $page
            );
        }

        if ($serverStr == 'www.vtb.rw:17000')
        {
            $arVariables = array();
            parse_str($queryStr, $arVariables);
 
            if (!isset($arVariables['text']))
                return false;

            $query = $this->DecodeString($arVariables['text']);
            $page = 1;
            if (isset($arVariables['p']))
            {
                $page = 1 + intval($arVariables['p']);
            }
            return array(
                'engine' => 'www.vtb.rw',
                'text' => $query,
                'page' => $page
            );
        }
        return false;
    }

    protected function ParseSearch(&$hit, $schemeStr, $serverStr, $pathStr, $queryStr)
    {
        $detectResult = $this->DetectSearch($serverStr, $pathStr, $queryStr);
        if ($detectResult === false)
            return false;

        $textId = $this->GetStringId($detectResult['text'], $hit['source']['time']);

        $hit['modules']['sources']['search']    = true;
        $hit['modules']['sources']['engine']    = $detectResult['engine'];
        $hit['modules']['sources']['text']      = $detectResult['text'];
        $hit['modules']['sources']['page']      = $detectResult['page'];

        $date   = '\'' . mysql_escape_string($hit['source']['time']) . '\'';
        $log    = intval($hit['modules']['popularity']['id']);
        $engine = '\'' . mysql_escape_string($detectResult['engine']) . '\'';
        $text   = intval($textId);
        $page   = intval($detectResult['page']);

        $InsertSQL = 'INSERT INTO `[PREF]module_sources_search` (`date`, `log`, `engine`, `text`, `page`) ';
        $InsertSQL .= 'VALUES('.$date.', '.$log.', '.$engine.', '.$text.', '.$page.')';
        $result = $this->database->Query($InsertSQL);
        if (!$result)
            trigger_error('Database Error: ' . $this->database->Error(), E_USER_ERROR);
        
        return true;
    }

    protected function ParseLink(&$hit, $schemeStr, $serverStr, $pathStr, $queryStr)
    {
        if ($hit['modules']['popularity']['serverStr'] == $serverStr || in_array($serverStr, LoggerConfig::$myServers))
            return false;
        $serverId   = $this->GetStringId($serverStr, $hit['source']['time']);
        $pathId     = $this->GetStringId($pathStr, $hit['source']['time']);
        $queryId    = $this->GetStringId($queryStr, $hit['source']['time']);

        $hit['modules']['sources']['link']  = true;
        $hit['modules']['sources']['schemeStr'] = $schemeStr;
        $hit['modules']['sources']['serverStr'] = $serverStr;
        $hit['modules']['sources']['pathStr']   = $pathStr;
        $hit['modules']['sources']['queryStr']  = $queryStr;

        $date   = '\'' . mysql_escape_string($hit['source']['time']) . '\'';
        $log    = intval($hit['modules']['popularity']['id']);
        $sheme   = '\'' . mysql_escape_string($schemeStr) . '\'';
        $serv   = intval($serverId);
        $path   = intval($pathId);
        $query  = intval($queryId);

        $InsertSQL = 'INSERT INTO `[PREF]module_sources_links` (`date`, `log`, `scheme`, `serv`, `path`, `query`) ';
        $InsertSQL .= 'VALUES('.$date.', '.$log.', '.$sheme.', '.$serv.', '.$path.', '.$query.')';
        $result = $this->database->Query($InsertSQL);
        if (!$result)
            trigger_error('Database Error: ' . $this->database->Error(), E_USER_ERROR);

        return true;
    }

    public function ParseHit(&$hit)
    {
        if (!isset($hit['modules']['popularity']))
            return false;
        if ($hit['source']['referer'] == '')
            return false;

        $parseUrlResult = $this->ParseUrl($hit['source']['referer']);
        if ($parseUrlResult === false)
            return false;

        $schemeStr  = $parseUrlResult['scheme'];
        $serverStr  = $parseUrlResult['server'];
        $pathStr    = $parseUrlResult['path'];
        $queryStr   = $parseUrlResult['query'];

        if (!$this->ParseSearch($hit, $schemeStr, $serverStr, $pathStr, $queryStr) || LoggerModuleSourcesConfig::$searchInLinks)
        {
            $this->ParseLink($hit, $schemeStr, $serverStr, $pathStr, $queryStr);
        }
        return true;
    }

    public function Archive()
    {
        $date = LoggerModuleSourcesConfig::GetArchiveDate();
        $dateEscaped = '\''.mysql_escape_string($date).'\'';

        $this->database->Query('LOCK TABLES `[PREF]module_sources_links` WRITE, `[PREF]module_sources_links_archive` WRITE');
        
        $ArchiveSQL = 'INSERT INTO `[PREF]module_sources_links_archive` (`date`, `scheme`, `serv`, `path`, `query`, `count`) ';
        $ArchiveSQL .= 'SELECT `date`, `scheme`, `serv`, `path`, `query`, COUNT(*) FROM `[PREF]module_sources_links` WHERE `date`<'.$dateEscaped.' ';
        $ArchiveSQL .= 'GROUP BY `date`, `scheme`, `serv`, `path`, `query`';
        $this->database->Query($ArchiveSQL);
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_links` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);
    
        $this->database->Query('UNLOCK TABLES');

        $this->database->Query('LOCK TABLES `[PREF]module_sources_search` WRITE, `[PREF]module_sources_search_archive` WRITE');
        
        $ArchiveSQL = 'INSERT INTO `[PREF]module_sources_search_archive` (`date`, `engine`, `text`, `page`, `count`) ';
        $ArchiveSQL .= 'SELECT `date`, `engine`, `text`, `page`, COUNT(*) FROM `[PREF]module_sources_search` WHERE `date`<'.$dateEscaped.' ';
        $ArchiveSQL .= 'GROUP BY `date`, `engine`, `text`, `page`';
        $this->database->Query($ArchiveSQL);
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_search` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);

        $this->database->Query('UNLOCK TABLES');
    }

    public function Purge()
    {
        $date = LoggerModuleSourcesConfig::GetPurgeDate();
        $dateEscaped = '\''.mysql_escape_string($date).'\'';
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_links_archive` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_links` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_search_archive` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);
        $DeleteSQL = 'DELETE FROM `[PREF]module_sources_search` WHERE `date`<'.$dateEscaped;
        $this->database->Query($DeleteSQL);

        $OptimizeSQL = 'OPTIMIZE TABLE `[PREF]module_sources_links`';
        $this->database->Query($OptimizeSQL);
        $OptimizeSQL = 'OPTIMIZE TABLE `[PREF]module_sources_links_archive`';
        $this->database->Query($OptimizeSQL);
        $OptimizeSQL = 'OPTIMIZE TABLE `[PREF]module_sources_search`';
        $this->database->Query($OptimizeSQL);
        $OptimizeSQL = 'OPTIMIZE TABLE `[PREF]module_sources_search_archive`';
        $this->database->Query($OptimizeSQL);

        $this->PurgeStrings($date);
    }
}